﻿using DotNetCommon.Extensions;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;

namespace DBUtil;

public partial class DBAccess
{
    #region 查询语句同步 Select...

    #region SelectScalar
    public virtual T SelectScalarOrDefault<T>(string sql) => SelectScalarOrDefault<T>(sql, null, null, []);

    public virtual T SelectScalarOrDefault<T>(string sql, IDictionary<string, object> parameters)
        => SelectScalarOrDefault<T>(sql, null, null, parameters?.Select(i => CreatePara(i.Key, i.Value)).ToArray());

    public virtual T SelectScalarOrDefault<T>(string sql, params DbParameter[] parameters)
        => SelectScalarOrDefault<T>(sql, null, null, parameters);

    public virtual T SelectScalarOrDefault<T>(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            return RunInCommand(cmd =>
            {
                var res = cmd.ExecuteScalar();
                if (res.IsNullOrDBNull()) return default;
                return res.To<T>();
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                }).Wait();
            }
        }
    }
    #endregion

    #region SelectScalar
    public virtual T SelectScalar<T>(string sql) => SelectScalar<T>(sql, null, null, []);

    public virtual T SelectScalar<T>(string sql, IDictionary<string, object> parameters)
        => SelectScalar<T>(sql, null, null, parameters?.Select(i => CreatePara(i.Key, i.Value)).ToArray());

    public virtual T SelectScalar<T>(string sql, params DbParameter[] parameters)
        => SelectScalar<T>(sql, null, null, parameters);

    public virtual T SelectScalar<T>(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            return RunInCommand(cmd =>
            {
                var res = cmd.ExecuteScalar();
                return res.To<T>();
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                }).Wait();
            }
        }
    }
    #endregion

    #region SelectDataSet
    public virtual DataSet SelectDataSet(string sql)
        => SelectDataSet(sql, null, null, []);

    public virtual DataSet SelectDataSet(string sql, params DbParameter[] parameters)
        => SelectDataSet(sql, null, null, parameters);

    public virtual DataSet SelectDataSet(string sql, IDictionary<string, object> parameters)
        => SelectDataSet(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual DataSet SelectDataSet(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        DataSet set = new();
        try
        {
            RunInCommand(cmd =>
            {
                using var adp = CreateAdapter(cmd);
                adp.Fill(set);
            }, sql, commandType, timeoutSecond, parameters);
            return set;
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                }).Wait();
            }
        }
    }
    #endregion

    #region SelectDataTable
    public virtual DataTable SelectDataTable(string sql)
        => SelectDataTable(sql, null, null, []);

    public virtual DataTable SelectDataTable(string sql, IDictionary<string, object> parameters)
        => SelectDataTable(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual DataTable SelectDataTable(string sql, params DbParameter[] parameters)
        => SelectDataTable(sql, null, null, parameters);

    public virtual DataTable SelectDataTable(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
        => SelectDataSet(sql, commandType, timeoutSecond, parameters).Tables[0];
    #endregion

    #region SelectDataReader

    #region SelectDataReader Action
    public virtual void SelectDataReader(Action<DBUtilDataReader> action, string sql)
        => SelectDataReader(action, sql, null, null, []);

    public virtual void SelectDataReader(Action<DBUtilDataReader> action, string sql, params DbParameter[] parameters)
        => SelectDataReader(action, sql, null, null, parameters);

    public virtual void SelectDataReader(Action<DBUtilDataReader> action, string sql, IDictionary<string, object> parameters)
        => SelectDataReader(action, sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual void SelectDataReader(Action<DBUtilDataReader> action, string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        if (action == null) throw new Exception("执行逻辑不能为空!");
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            RunInCommand(cmd =>
            {
                var reader = cmd.ExecuteReader();
                try
                {
                    action.Invoke(new DBUtilDataReader { RawReader = reader, db = this });
                }
                finally
                {
                    if (!reader.IsClosed)
                    {
                        try { reader.Close(); }
                        catch (Exception ex) { logger.LogError(ex, $"释放 DbDataReader 时报错:{ex.Message}"); };
                    }
                }
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                }).Wait();
            }
        }
    }
    #endregion

    #region SelectDataReader Func
    public virtual T SelectDataReader<T>(Func<DBUtilDataReader, T> func, string sql)
        => SelectDataReader(func, sql, null, null, []);

    public virtual T SelectDataReader<T>(Func<DBUtilDataReader, T> func, string sql, params DbParameter[] parameters)
        => SelectDataReader(func, sql, null, null, parameters);

    public virtual T SelectDataReader<T>(Func<DBUtilDataReader, T> func, string sql, IDictionary<string, object> parameters)
        => SelectDataReader(func, sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual T SelectDataReader<T>(Func<DBUtilDataReader, T> func, string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return (T)SelectDataReader(typeof(T), reader => func(reader), sql, commandType, timeoutSecond, parameters);
    }

    public virtual object SelectDataReader(Type type, Func<DBUtilDataReader, object> func, string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        if (func == null) throw new Exception("执行逻辑不能为空!");
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            return RunInCommand(cmd =>
            {
                var reader = cmd.ExecuteReader();
                try
                {
                    object result = type.GetDefault();
                    if (func != null) result = func(new DBUtilDataReader { RawReader = reader, db = this });
                    return result;
                }
                finally
                {
                    if (!reader.IsClosed)
                    {
                        try { reader.Close(); }
                        catch (Exception ex) { logger.LogError(ex, $"释放 DbDataReader 时报错:{ex.Message}"); };
                    }
                }
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                }).Wait();
            }
        }
    }
    #endregion

    #endregion

    #region SelectModel & SelectModelList

    #region SelectModelOrDefault
    public virtual T SelectModelOrDefault<T>(string sql)
        => SelectModelOrDefault<T>(sql, null, null, []);

    public virtual T SelectModelOrDefault<T>(string sql, IDictionary<string, object> parameters)
        => SelectModelOrDefault<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual T SelectModelOrDefault<T>(string sql, params DbParameter[] parameters)
        => SelectModelOrDefault<T>(sql, null, null, parameters);

    public virtual T SelectModelOrDefault<T>(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return SelectDataReader<T>(reader => reader.ReadOneOrDefault<T>(), sql, commandType, timeoutSecond, parameters);
    }
    public virtual object SelectModelOrDefault(Type type, string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return SelectDataReader(type, (DBUtilDataReader reader) => reader.ReadOneOrDefault(type), sql, commandType, timeoutSecond, parameters);
    }
    #endregion

    #region SelectModel
    public virtual T SelectModel<T>(string sql)
        => SelectModel<T>(sql, null, null, []);

    public virtual T SelectModel<T>(string sql, IDictionary<string, object> parameters)
        => SelectModel<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual T SelectModel<T>(string sql, params DbParameter[] parameters)
        => SelectModel<T>(sql, null, null, parameters);

    public virtual T SelectModel<T>(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return SelectDataReader<T>(reader => reader.ReadOne<T>(), sql, commandType, timeoutSecond, parameters);
    }
    public virtual object SelectModel(Type type, string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return SelectDataReader(type, (DBUtilDataReader reader) => reader.ReadOne(type), sql, commandType, timeoutSecond, parameters);
    }
    #endregion

    #region SelectModelList
    public virtual List<T> SelectModelList<T>(string sql)
        => SelectModelList<T>(sql, null, null, []);

    public virtual List<T> SelectModelList<T>(string sql, params DbParameter[] parameters)
       => SelectModelList<T>(sql, null, null, parameters);

    public virtual List<T> SelectModelList<T>(string sql, IDictionary<string, object> parameters)
      => SelectModelList<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual List<T> SelectModelList<T>(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return SelectDataReader(reader => reader.ReadList<T>(), sql, commandType, timeoutSecond, parameters);
    }
    #endregion

    #endregion

    #region SelectDictionary & SelectDictionaryList

    #region SelectDictionary
    public virtual Dictionary<string, object> SelectDictionary(string sql)
        => SelectDictionary(sql, null, null, []);

    public virtual Dictionary<string, object> SelectDictionary(string sql, params DbParameter[] parameters)
        => SelectDictionary(sql, null, null, parameters);

    public virtual Dictionary<string, object> SelectDictionary(string sql, IDictionary<string, object> parameters)
        => SelectDictionary(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual Dictionary<string, object> SelectDictionary(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return SelectDataReader(reader =>
        {
            Dictionary<string, object> dic = null;
            var count = reader.RawReader.FieldCount;
            if (reader.RawReader.Read())
            {
                dic = [];
                for (int i = 0; i < count; i++)
                {
                    dic[reader.RawReader.GetName(i)] = reader.RawReader.GetValue(i);
                }
            }
            return dic;
        }, sql, commandType, timeoutSecond, parameters);
    }
    #endregion

    #region SelectDictionaryList
    public virtual List<Dictionary<string, object>> SelectDictionaryList(string sql)
        => SelectDictionaryList(sql, null, null, []);

    public virtual List<Dictionary<string, object>> SelectDictionaryList(string sql, params DbParameter[] parameters)
        => SelectDictionaryList(sql, null, null, parameters);

    public virtual List<Dictionary<string, object>> SelectDictionaryList(string sql, IDictionary<string, object> parameters)
        => SelectDictionaryList(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual List<Dictionary<string, object>> SelectDictionaryList(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return SelectDataReader(reader =>
        {
            var count = reader.RawReader.FieldCount;
            var names = new string[count];
            for (int i = 0; i < count; i++)
            {
                names[i] = reader.RawReader.GetName(i);
            }
            var list = new List<Dictionary<string, object>>();
            while (reader.RawReader.Read())
            {
                var dic = new Dictionary<string, object>();
                list.Add(dic);
                for (int i = 0; i < count; i++)
                {
                    dic[names[i]] = reader.RawReader.GetValue(i);
                }
            }
            return list;
        }, sql, commandType, timeoutSecond, parameters);
    }
    #endregion

    #endregion

    #region SelectMultiple
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2) SelectMultiple<T, T2>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            return (t1, t2);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3) SelectMultiple<T, T2, T3>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            return (t1, t2, t3);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3, T4) SelectMultiple<T, T2, T3, T4>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , Func<DBUtilDataReader, T4> func4
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            reader.RawReader.NextResult();
            var t4 = func4(reader);
            return (t1, t2, t3, t4);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3, T4, T5) SelectMultiple<T, T2, T3, T4, T5>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , Func<DBUtilDataReader, T4> func4
        , Func<DBUtilDataReader, T5> func5
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            reader.RawReader.NextResult();
            var t4 = func4(reader);
            reader.RawReader.NextResult();
            var t5 = func5(reader);
            return (t1, t2, t3, t4, t5);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3, T4, T5, T6) SelectMultiple<T, T2, T3, T4, T5, T6>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , Func<DBUtilDataReader, T4> func4
        , Func<DBUtilDataReader, T5> func5
        , Func<DBUtilDataReader, T6> func6
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            reader.RawReader.NextResult();
            var t4 = func4(reader);
            reader.RawReader.NextResult();
            var t5 = func5(reader);
            reader.RawReader.NextResult();
            var t6 = func6(reader);
            return (t1, t2, t3, t4, t5, t6);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3, T4, T5, T6, T7) SelectMultiple<T, T2, T3, T4, T5, T6, T7>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , Func<DBUtilDataReader, T4> func4
        , Func<DBUtilDataReader, T5> func5
        , Func<DBUtilDataReader, T6> func6
        , Func<DBUtilDataReader, T7> func7
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            reader.RawReader.NextResult();
            var t4 = func4(reader);
            reader.RawReader.NextResult();
            var t5 = func5(reader);
            reader.RawReader.NextResult();
            var t6 = func6(reader);
            reader.RawReader.NextResult();
            var t7 = func7(reader);
            return (t1, t2, t3, t4, t5, t6, t7);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3, T4, T5, T6, T7, T8) SelectMultiple<T, T2, T3, T4, T5, T6, T7, T8>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , Func<DBUtilDataReader, T4> func4
        , Func<DBUtilDataReader, T5> func5
        , Func<DBUtilDataReader, T6> func6
        , Func<DBUtilDataReader, T7> func7
        , Func<DBUtilDataReader, T8> func8
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            reader.RawReader.NextResult();
            var t4 = func4(reader);
            reader.RawReader.NextResult();
            var t5 = func5(reader);
            reader.RawReader.NextResult();
            var t6 = func6(reader);
            reader.RawReader.NextResult();
            var t7 = func7(reader);
            reader.RawReader.NextResult();
            var t8 = func8(reader);
            return (t1, t2, t3, t4, t5, t6, t7, t8);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3, T4, T5, T6, T7, T8, T9) SelectMultiple<T, T2, T3, T4, T5, T6, T7, T8, T9>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , Func<DBUtilDataReader, T4> func4
        , Func<DBUtilDataReader, T5> func5
        , Func<DBUtilDataReader, T6> func6
        , Func<DBUtilDataReader, T7> func7
        , Func<DBUtilDataReader, T8> func8
        , Func<DBUtilDataReader, T9> func9
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            reader.RawReader.NextResult();
            var t4 = func4(reader);
            reader.RawReader.NextResult();
            var t5 = func5(reader);
            reader.RawReader.NextResult();
            var t6 = func6(reader);
            reader.RawReader.NextResult();
            var t7 = func7(reader);
            reader.RawReader.NextResult();
            var t8 = func8(reader);
            reader.RawReader.NextResult();
            var t9 = func9(reader);
            return (t1, t2, t3, t4, t5, t6, t7, t8, t9);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual (T, T2, T3, T4, T5, T6, T7, T8, T9, T10) SelectMultiple<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>(string sql
        , Func<DBUtilDataReader, T> func
        , Func<DBUtilDataReader, T2> func2
        , Func<DBUtilDataReader, T3> func3
        , Func<DBUtilDataReader, T4> func4
        , Func<DBUtilDataReader, T5> func5
        , Func<DBUtilDataReader, T6> func6
        , Func<DBUtilDataReader, T7> func7
        , Func<DBUtilDataReader, T8> func8
        , Func<DBUtilDataReader, T9> func9
        , Func<DBUtilDataReader, T10> func10
        , int? timeoutSecond = null)
    {
        return SelectDataReader((reader) =>
        {
            var t1 = func(reader);
            reader.RawReader.NextResult();
            var t2 = func2(reader);
            reader.RawReader.NextResult();
            var t3 = func3(reader);
            reader.RawReader.NextResult();
            var t4 = func4(reader);
            reader.RawReader.NextResult();
            var t5 = func5(reader);
            reader.RawReader.NextResult();
            var t6 = func6(reader);
            reader.RawReader.NextResult();
            var t7 = func7(reader);
            reader.RawReader.NextResult();
            var t8 = func8(reader);
            reader.RawReader.NextResult();
            var t9 = func9(reader);
            reader.RawReader.NextResult();
            var t10 = func10(reader);
            return (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
        }, sql, commandType: null, timeoutSecond: timeoutSecond);
    }
    #endregion

    #endregion

    #region 查询语句异步 Select...

    #region SelectScalarOrDefaultAsync
    public async virtual Task<T> SelectScalarOrDefaultAsync<T>(string sql, CancellationToken cancellationToken = default)
        => await SelectScalarOrDefaultAsync<T>(sql, null, null, null, cancellationToken);

    public async virtual Task<T> SelectScalarOrDefaultAsync<T>(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectScalarOrDefaultAsync<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task<T> SelectScalarOrDefaultAsync<T>(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectScalarOrDefaultAsync<T>(sql, null, null, parameters, cancellationToken);

    public async virtual Task<T> SelectScalarOrDefaultAsync<T>(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            return await RunInCommandAsync(async cmd =>
            {
                var res = await cmd.ExecuteScalarAsync(cancellationToken);
                if (res.IsNullOrDBNull()) return default;
                return res.To<T>();
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                await Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                });
            }
        }
    }
    #endregion

    #region SelectScalarAsync
    public async virtual Task<T> SelectScalarAsync<T>(string sql, CancellationToken cancellationToken = default)
        => await SelectScalarAsync<T>(sql, null, null, null, cancellationToken);

    public async virtual Task<T> SelectScalarAsync<T>(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectScalarAsync<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task<T> SelectScalarAsync<T>(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectScalarAsync<T>(sql, null, null, parameters, cancellationToken);

    public async virtual Task<T> SelectScalarAsync<T>(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            return await RunInCommandAsync(async cmd =>
            {
                var res = await cmd.ExecuteScalarAsync(cancellationToken);
                return res.To<T>();
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                await Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                });
            }
        }
    }
    #endregion

    #region SelectDataSetAsync
    public virtual async Task<DataSet> SelectDataSetAsync(string sql, CancellationToken cancellationToken = default)
        => await SelectDataSetAsync(sql, null, null, null, cancellationToken);

    public virtual async Task<DataSet> SelectDataSetAsync(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectDataSetAsync(sql, null, null, parameters, cancellationToken);

    public virtual async Task<DataSet> SelectDataSetAsync(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectDataSetAsync(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public virtual async Task<DataSet> SelectDataSetAsync(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        //这里不用再使用 RunInCommand 包裹, 也不用再检测耗时, 因为 SelectDataReaderAsync 里面已经做了
        return await SelectDataReaderAsync(async reader =>
        {
            DataSet set = new();
            do
            {
                var dt = new DataTable();
                var count = reader.RawReader.FieldCount;
                for (int i = 0; i < count; i++)
                {
                    dt.Columns.Add(new DataColumn(reader.RawReader.GetName(i), reader.RawReader.GetFieldType(i)));
                }
                while (await reader.RawReader.ReadAsync(cancellationToken))
                {
                    var arr = new object[count];
                    reader.RawReader.GetValues(arr);
                    dt.Rows.Add(arr);
                }
                set.Tables.Add(dt);
            } while (await reader.RawReader.NextResultAsync(cancellationToken));
            return set;
        }, sql, commandType, timeoutSecond, parameters, cancellationToken);
    }
    #endregion

    #region SelectDataTableAsync
    public virtual async Task<DataTable> SelectDataTableAsync(string sql, CancellationToken cancellationToken = default)
        => await SelectDataTableAsync(sql, null, null, null, cancellationToken);

    public virtual async Task<DataTable> SelectDataTableAsync(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectDataTableAsync(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public virtual async Task<DataTable> SelectDataTableAsync(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectDataTableAsync(sql, null, null, parameters, cancellationToken);

    public virtual async Task<DataTable> SelectDataTableAsync(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        //这里不用再使用 RunInCommand 包裹, 也不用再检测耗时, 因为 SelectDataReaderAsync 里面已经做了
        return await SelectDataReaderAsync(async reader =>
        {
            var dt = new DataTable();
            var count = reader.RawReader.FieldCount;
            for (int i = 0; i < count; i++)
            {
                dt.Columns.Add(new DataColumn(reader.RawReader.GetName(i), reader.RawReader.GetFieldType(i)));
            }
            while (await reader.RawReader.ReadAsync(cancellationToken))
            {
                var arr = new object[count];
                reader.RawReader.GetValues(arr);
                dt.Rows.Add(arr);
            }
            return dt;
        }, sql, commandType, timeoutSecond, parameters, cancellationToken);
    }
    #endregion

    #region SelectDataReaderAsync

    #region SelectDataReaderAsync Action
    public async virtual Task SelectDataReaderAsync(Func<DBUtilDataReader, Task> func, string sql, CancellationToken cancellationToken = default)
        => await SelectDataReaderAsync(func, sql, null, null, null, cancellationToken);

    public async virtual Task SelectDataReaderAsync(Func<DBUtilDataReader, Task> func, string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectDataReaderAsync(func, sql, null, null, parameters, cancellationToken);

    public async virtual Task SelectDataReaderAsync(Func<DBUtilDataReader, Task> func, string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectDataReaderAsync(func, sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task SelectDataReaderAsync(Func<DBUtilDataReader, Task> func, string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        if (func == null) throw new Exception("执行的逻辑不能为空!");
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            await RunInCommandAsync(async cmd =>
            {
                var reader = await cmd.ExecuteReaderAsync(cancellationToken);
                try
                {
                    await func(new DBUtilDataReader { RawReader = reader, db = this });
                }
                finally
                {
                    if (!reader.IsClosed)
                    {
                        try { await reader.CloseAsync(); }
                        catch (Exception ex) { logger.LogError(ex, $"释放 DbDataReader 时报错:{ex.Message}"); };
                    }
                }
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                await Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Sql = sql,
                    Exception = ex,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                });
            }
        }
    }
    #endregion

    #region SelectDataReaderAsync Func
    public async virtual Task<T> SelectDataReaderAsync<T>(Func<DBUtilDataReader, Task<T>> func, string sql, CancellationToken cancellationToken = default)
        => await SelectDataReaderAsync(func, sql, null, null, null, cancellationToken);

    public async virtual Task<T> SelectDataReaderAsync<T>(Func<DBUtilDataReader, Task<T>> func, string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectDataReaderAsync(func, sql, null, null, parameters, cancellationToken);

    public async virtual Task<T> SelectDataReaderAsync<T>(Func<DBUtilDataReader, Task<T>> func, string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectDataReaderAsync(func, sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task<T> SelectDataReaderAsync<T>(Func<DBUtilDataReader, Task<T>> func, string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        return (T)await SelectDataReaderAsync(typeof(T), async (reader) => await func(reader), sql, commandType, timeoutSecond, parameters, cancellationToken);
    }

    public async virtual Task<object> SelectDataReaderAsync(Type type, Func<DBUtilDataReader, Task<object>> func, string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        if (func == null) throw new Exception("执行的逻辑不能为空!");
        Stopwatch st = null;
        Exception ex = null;
        if (Setting.HasMonitor) { st = new Stopwatch(); st.Start(); }
        try
        {
            return await RunInCommandAsync(async cmd =>
            {
                var reader = await cmd.ExecuteReaderAsync(cancellationToken);
                try
                {
                    object result = type.GetDefault();
                    if (func != null) result = await func(new DBUtilDataReader { RawReader = reader, db = this });
                    return result;
                }
                finally
                {
                    if (!reader.IsClosed)
                    {
                        try { await reader.CloseAsync(); }
                        catch (Exception ex) { logger.LogError(ex, $"释放 DbDataReader 时报错:{ex.Message}"); };
                    }
                }
            }, sql, commandType, timeoutSecond, parameters);
        }
        catch (Exception e)
        {
            if (Setting.HasMonitor) ex = e;
            throw;
        }
        finally
        {
            if (Setting.HasMonitor)
            {
                if (st.IsRunning) st.Stop();
                await Setting.MonitorAction?.Invoke(new MonitorArgument
                {
                    Exception = ex,
                    Sql = sql,
                    TimeSpan = TimeSpan.FromMilliseconds(st.ElapsedMilliseconds)
                });
            }
        }
    }
    #endregion

    #endregion

    #region SelectModelAsync & SelectModelListAsync

    #region SelectModelOrDefaultAsync
    public virtual async Task<T> SelectModelOrDefaultAsync<T>(string sql)
        => await SelectModelOrDefaultAsync<T>(sql, null, null, []);

    public virtual async Task<T> SelectModelOrDefaultAsync<T>(string sql, IDictionary<string, object> parameters)
        => await SelectModelOrDefaultAsync<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray());

    public virtual async Task<T> SelectModelOrDefaultAsync<T>(string sql, params DbParameter[] parameters)
        => await SelectModelOrDefaultAsync<T>(sql, null, null, parameters);

    public virtual async Task<T> SelectModelOrDefaultAsync<T>(string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return await SelectDataReaderAsync<T>(async reader => await reader.ReadOneOrDefaultAsync<T>(), sql, commandType, timeoutSecond, parameters);
    }
    public virtual async Task<object> SelectModelOrDefaultAsync(Type type, string sql, CommandType? commandType, int? timeoutSecond, params DbParameter[] parameters)
    {
        return await SelectDataReaderAsync(type, async (DBUtilDataReader reader) => await reader.ReadOneOrDefaultAsync(type), sql, commandType, timeoutSecond, parameters);
    }
    #endregion

    #region SelectModelAsync
    public async virtual Task<T> SelectModelAsync<T>(string sql, CancellationToken cancellationToken = default)
        => await SelectModelAsync<T>(sql, null, null, null, cancellationToken);

    public async virtual Task<T> SelectModelAsync<T>(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectModelAsync<T>(sql, null, null, parameters, cancellationToken);

    public async virtual Task<T> SelectModelAsync<T>(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectModelAsync<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task<T> SelectModelAsync<T>(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync(async reader => await reader.ReadOneAsync<T>(), sql, commandType, timeoutSecond, parameters, cancellationToken);
    }
    public async virtual Task<object> SelectModelAsync(Type type, string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync(type, async reader => await reader.ReadOneAsync(type), sql, commandType, timeoutSecond, parameters, cancellationToken);
    }
    #endregion

    #region SelectModelListAsync
    public async virtual Task<List<T>> SelectModelListAsync<T>(string sql, CancellationToken cancellationToken = default)
        => await SelectModelListAsync<T>(sql, null, null, null, cancellationToken);

    public async virtual Task<List<T>> SelectModelListAsync<T>(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectModelListAsync<T>(sql, null, null, parameters, cancellationToken);

    public async virtual Task<List<T>> SelectModelListAsync<T>(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectModelListAsync<T>(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task<List<T>> SelectModelListAsync<T>(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync(async reader => await reader.ReadListAsync<T>(), sql, commandType, timeoutSecond, parameters, cancellationToken);
    }
    #endregion

    #endregion

    #region SelectDictionaryAsync & SelectDictionaryListAsync

    #region SelectDictionaryAsync
    public async virtual Task<Dictionary<string, object>> SelectDictionaryAsync(string sql, CancellationToken cancellationToken = default)
        => await SelectDictionaryAsync(sql, null, null, null, cancellationToken);

    public async virtual Task<Dictionary<string, object>> SelectDictionaryAsync(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectDictionaryAsync(sql, null, null, parameters, cancellationToken);

    public async virtual Task<Dictionary<string, object>> SelectDictionaryAsync(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectDictionaryAsync(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task<Dictionary<string, object>> SelectDictionaryAsync(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync(async reader =>
        {
            Dictionary<string, object> dic = null;
            var count = reader.RawReader.FieldCount;
            if (await reader.RawReader.ReadAsync(cancellationToken))
            {
                dic = [];
                for (int i = 0; i < count; i++)
                {
                    dic[reader.RawReader.GetName(i)] = reader.RawReader.GetValue(i);
                }
            }
            return dic;
        }, sql, commandType, timeoutSecond, parameters, cancellationToken);
    }
    #endregion

    #region SelectDictionaryListAsync
    public async virtual Task<List<Dictionary<string, object>>> SelectDictionaryListAsync(string sql, CancellationToken cancellationToken = default)
        => await SelectDictionaryListAsync(sql, null, null, null, cancellationToken);

    public async virtual Task<List<Dictionary<string, object>>> SelectDictionaryListAsync(string sql, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
        => await SelectDictionaryListAsync(sql, null, null, parameters, cancellationToken);

    public async virtual Task<List<Dictionary<string, object>>> SelectDictionaryListAsync(string sql, IDictionary<string, object> parameters, CancellationToken cancellationToken = default)
        => await SelectDictionaryListAsync(sql, null, null, parameters?.Select(x => CreatePara(x.Key, x.Value)).ToArray(), cancellationToken);

    public async virtual Task<List<Dictionary<string, object>>> SelectDictionaryListAsync(string sql, CommandType? commandType, int? timeoutSecond, IEnumerable<DbParameter> parameters, CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync(async reader =>
        {
            var count = reader.RawReader.FieldCount;
            var names = new string[count];
            for (int i = 0; i < count; i++)
            {
                names[i] = reader.RawReader.GetName(i);
            }
            var list = new List<Dictionary<string, object>>();
            while (await reader.RawReader.ReadAsync(cancellationToken))
            {
                var dic = new Dictionary<string, object>();
                list.Add(dic);
                for (int i = 0; i < count; i++)
                {
                    dic[names[i]] = reader.RawReader.GetValue(i);
                }
            }
            return list;
        }, sql, commandType, timeoutSecond, parameters, cancellationToken);
    }
    #endregion

    #endregion

    #region SelectMultipleAsync
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2)> SelectMultipleAsync<T, T2>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            return (t1, t2);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3)> SelectMultipleAsync<T, T2, T3>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            return (t1, t2, t3);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3, T4)> SelectMultipleAsync<T, T2, T3, T4>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , Func<DBUtilDataReader, Task<T4>> func4
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3, T4)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            await reader.RawReader.NextResultAsync();
            var t4 = await func4(reader);
            return (t1, t2, t3, t4);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3, T4, T5)> SelectMultipleAsync<T, T2, T3, T4, T5>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , Func<DBUtilDataReader, Task<T4>> func4
        , Func<DBUtilDataReader, Task<T5>> func5
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3, T4, T5)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            await reader.RawReader.NextResultAsync();
            var t4 = await func4(reader);
            await reader.RawReader.NextResultAsync();
            var t5 = await func5(reader);
            return (t1, t2, t3, t4, t5);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3, T4, T5, T6)> SelectMultipleAsync<T, T2, T3, T4, T5, T6>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , Func<DBUtilDataReader, Task<T4>> func4
        , Func<DBUtilDataReader, Task<T5>> func5
        , Func<DBUtilDataReader, Task<T6>> func6
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3, T4, T5, T6)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            await reader.RawReader.NextResultAsync();
            var t4 = await func4(reader);
            await reader.RawReader.NextResultAsync();
            var t5 = await func5(reader);
            await reader.RawReader.NextResultAsync();
            var t6 = await func6(reader);
            return (t1, t2, t3, t4, t5, t6);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3, T4, T5, T6, T7)> SelectMultipleAsync<T, T2, T3, T4, T5, T6, T7>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , Func<DBUtilDataReader, Task<T4>> func4
        , Func<DBUtilDataReader, Task<T5>> func5
        , Func<DBUtilDataReader, Task<T6>> func6
        , Func<DBUtilDataReader, Task<T7>> func7
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3, T4, T5, T6, T7)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            await reader.RawReader.NextResultAsync();
            var t4 = await func4(reader);
            await reader.RawReader.NextResultAsync();
            var t5 = await func5(reader);
            await reader.RawReader.NextResultAsync();
            var t6 = await func6(reader);
            await reader.RawReader.NextResultAsync();
            var t7 = await func7(reader);
            return (t1, t2, t3, t4, t5, t6, t7);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3, T4, T5, T6, T7, T8)> SelectMultipleAsync<T, T2, T3, T4, T5, T6, T7, T8>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , Func<DBUtilDataReader, Task<T4>> func4
        , Func<DBUtilDataReader, Task<T5>> func5
        , Func<DBUtilDataReader, Task<T6>> func6
        , Func<DBUtilDataReader, Task<T7>> func7
        , Func<DBUtilDataReader, Task<T8>> func8
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3, T4, T5, T6, T7, T8)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            await reader.RawReader.NextResultAsync();
            var t4 = await func4(reader);
            await reader.RawReader.NextResultAsync();
            var t5 = await func5(reader);
            await reader.RawReader.NextResultAsync();
            var t6 = await func6(reader);
            await reader.RawReader.NextResultAsync();
            var t7 = await func7(reader);
            await reader.RawReader.NextResultAsync();
            var t8 = await func8(reader);
            return (t1, t2, t3, t4, t5, t6, t7, t8);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3, T4, T5, T6, T7, T8, T9)> SelectMultipleAsync<T, T2, T3, T4, T5, T6, T7, T8, T9>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , Func<DBUtilDataReader, Task<T4>> func4
        , Func<DBUtilDataReader, Task<T5>> func5
        , Func<DBUtilDataReader, Task<T6>> func6
        , Func<DBUtilDataReader, Task<T7>> func7
        , Func<DBUtilDataReader, Task<T8>> func8
        , Func<DBUtilDataReader, Task<T9>> func9
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3, T4, T5, T6, T7, T8, T9)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            await reader.RawReader.NextResultAsync();
            var t4 = await func4(reader);
            await reader.RawReader.NextResultAsync();
            var t5 = await func5(reader);
            await reader.RawReader.NextResultAsync();
            var t6 = await func6(reader);
            await reader.RawReader.NextResultAsync();
            var t7 = await func7(reader);
            await reader.RawReader.NextResultAsync();
            var t8 = await func8(reader);
            await reader.RawReader.NextResultAsync();
            var t9 = await func9(reader);
            return (t1, t2, t3, t4, t5, t6, t7, t8, t9);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    /// <summary>
    /// 批量查询(返回多个结果集)
    /// </summary>
    public virtual async Task<(T, T2, T3, T4, T5, T6, T7, T8, T9, T10)> SelectMultipleAsync<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>(string sql
        , Func<DBUtilDataReader, Task<T>> func
        , Func<DBUtilDataReader, Task<T2>> func2
        , Func<DBUtilDataReader, Task<T3>> func3
        , Func<DBUtilDataReader, Task<T4>> func4
        , Func<DBUtilDataReader, Task<T5>> func5
        , Func<DBUtilDataReader, Task<T6>> func6
        , Func<DBUtilDataReader, Task<T7>> func7
        , Func<DBUtilDataReader, Task<T8>> func8
        , Func<DBUtilDataReader, Task<T9>> func9
        , Func<DBUtilDataReader, Task<T10>> func10
        , int? timeoutSecond = null
        , CancellationToken cancellationToken = default)
    {
        return await SelectDataReaderAsync<(T, T2, T3, T4, T5, T6, T7, T8, T9, T10)>(async (reader) =>
        {
            var t1 = await func(reader);
            await reader.RawReader.NextResultAsync();
            var t2 = await func2(reader);
            await reader.RawReader.NextResultAsync();
            var t3 = await func3(reader);
            await reader.RawReader.NextResultAsync();
            var t4 = await func4(reader);
            await reader.RawReader.NextResultAsync();
            var t5 = await func5(reader);
            await reader.RawReader.NextResultAsync();
            var t6 = await func6(reader);
            await reader.RawReader.NextResultAsync();
            var t7 = await func7(reader);
            await reader.RawReader.NextResultAsync();
            var t8 = await func8(reader);
            await reader.RawReader.NextResultAsync();
            var t9 = await func9(reader);
            await reader.RawReader.NextResultAsync();
            var t10 = await func10(reader);
            return (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
        }, sql, commandType: null, timeoutSecond: timeoutSecond, parameters: null, cancellationToken: cancellationToken);
    }
    #endregion

    #endregion
}
